package com.chinamobile.iot.mqtt.spi.impl.security;

import com.chinamobile.iot.extend.auth.IMqttAuthRestClient;
import com.chinamobile.iot.mqtt.spi.security.IAuthorizator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;

import static com.chinamobile.iot.mqtt.spi.impl.security.BaasTopicAuthorizator.TopicType.*;

@Component
@ConditionalOnExpression("${mqtt.anonymous}==false ")
public class BaasTopicAuthorizator implements IAuthorizator {

    @Autowired
    private IMqttAuthRestClient mqttAuthRestClient;

    @Override
    public boolean canWrite(String topic, String clientId, String mqttId, String content) {
        return true;
    }

    @Override
    public boolean canRead(String topic, String clientId, String mqttId) {
        return topicPermission(getTopicModel(topic), mqttId);
    }

    @Override
    public String getProxy(String mqttId, String type) {
        return null;
    }

    @Override
    public void cleanProxy(String mqttId) {

    }

    @Override
    public String getCmdTopic(String clientId, String mqttId) {
        return null;
    }

    private boolean topicPermission(TopicModel topicModel, String mqttId) {
        boolean bPermit = false;

        switch (topicModel.getTopicType()) {
            case DEVICE_ALARM:
                bPermit = mqttAuthRestClient.deviceAlarmPermission(topicModel.getDeviceId(), topicModel.getType(), mqttId);
                break;
            case DEVICE_DATA:
                bPermit = mqttAuthRestClient.deviceDataPermission(topicModel.getDeviceId(), topicModel.getType(), topicModel.getField(), mqttId);
                break;
            case DEVICE_STAT:
                bPermit = mqttAuthRestClient.deviceStatPermission(topicModel.getDeviceId(), topicModel.getType(), topicModel.getField(), mqttId);
                break;
            case DEVICE_STATE:
                bPermit = mqttAuthRestClient.deviceStatePermission(topicModel.getDeviceId(), mqttId);
                break;
            case ALARM:
                bPermit = mqttAuthRestClient.alarmPermission(topicModel.getType(), mqttId);
                break;
            case STAT:
                bPermit = mqttAuthRestClient.statPermission(topicModel.getType(), topicModel.getField(), mqttId);
                break;
            case NOT_DEFINE:
                bPermit = false;
                break;
        }
        return bPermit;
    }

    private TopicModel getTopicModel(String topic) {
        TopicModel topicModel = new TopicModel();
        if (null != topic) {
            String[] results = topic.split("/");
            switch (results.length) {
                case 5:
                    if ("data".equals(results[2])) {
                        topicModel.setTopicType(DEVICE_DATA);
                        topicModel.setDeviceId(results[2]);
                        topicModel.setType(results[3]);
                        topicModel.setField(results[4]);
                    } else if ("stat".equals(results[2])) {
                        topicModel.setTopicType(DEVICE_STAT);
                        topicModel.setDeviceId(results[2]);
                        topicModel.setType(results[3]);
                        topicModel.setField(results[4]);
                    } else {
                        topicModel.setTopicType(NOT_DEFINE);
                    }
                    break;
                case 4:
                    if ("alarm".equals(results[2])) {
                        topicModel.setTopicType(DEVICE_ALARM);
                        topicModel.setDeviceId(results[1]);
                        topicModel.setType(results[3]);
                    } else if ("stat".equals(results[1])) {
                        topicModel.setTopicType(STAT);
                        topicModel.setType(results[2]);
                        topicModel.setField(results[3]);
                    } else {
                        topicModel.setTopicType(NOT_DEFINE);
                    }
                    break;
                case 3:
                    if ("alarm".equals(results[1])) {
                        topicModel.setTopicType(ALARM);
                        topicModel.setType(results[2]);
                    } else if ("deviceState".equals(results[2])) {
                        topicModel.setTopicType(DEVICE_STATE);
                    } else {
                        topicModel.setTopicType(NOT_DEFINE);
                    }
                    break;
                default:
                    topicModel.setTopicType(NOT_DEFINE);
            }
        }
        return topicModel;
    }

    enum TopicType {
        DEVICE_ALARM,
        DEVICE_DATA,
        DEVICE_STAT,
        DEVICE_STATE,
        ALARM,
        STAT,
        NOT_DEFINE
    }

    class TopicModel {
        private TopicType topicType;
        private String deviceId;
        private String type;
        private String field;

        public TopicType getTopicType() {
            return topicType;
        }

        public void setTopicType(TopicType topicType) {
            this.topicType = topicType;
        }

        public String getDeviceId() {
            return deviceId;
        }

        public void setDeviceId(String deviceId) {
            this.deviceId = deviceId;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getField() {
            return field;
        }

        public void setField(String field) {
            this.field = field;
        }

        @Override
        public String toString() {
            return "TopicModel{" +
                    "topicType=" + topicType +
                    ", deviceId='" + deviceId + '\'' +
                    ", type='" + type + '\'' +
                    ", field='" + field + '\'' +
                    '}';
        }
    }
}